package com.xmut.mall.manager.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xmut.mall.manager.constant.AuthConstant;
import com.xmut.mall.manager.dao.MenuDao;
import com.xmut.mall.manager.entity.MemberEntity;
import com.xmut.mall.manager.entity.MenuEntity;
import com.xmut.mall.manager.service.MemberService;
import com.xmut.mall.manager.service.MenuService;
import com.xmut.mall.manager.utils.RespBean;
import com.xmut.mall.manager.vo.MenuVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Comparator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service("menuService")
public class MenuServiceImpl extends ServiceImpl<MenuDao, MenuEntity> implements MenuService {

    @Autowired
    private MemberService memberService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 管理端登录时获取根据用户权限获取菜单
     *
     * @param memberId
     * @return
     */
    @Override
    public RespBean getUserMenu(Long memberId) {
        // 先获取当前用户
        MemberEntity member = memberService.getOne(new QueryWrapper<MemberEntity>().eq("id", memberId));
        if (member != null) {
            if ("admin".equals(member.getUserAuth())) {
                // 如果用户的权限是管理员就直接给他全部菜单
                String menu = redisTemplate.opsForValue().get(AuthConstant.MENU_CACHE);
                if (!StringUtils.isEmpty(menu)) {
                    // 如果redis查缓存不是null
                    List<MenuEntity> menuList = JSON.parseObject(menu, new TypeReference<List<MenuEntity>>() {
                    });
                    // 组装为三级结构
                    List<MenuVo> vos = this.tree(menuList);
                    return RespBean.success("获取菜单成功", vos);
                } else {
                    // 如果redis查缓存是null直接查数据库
                    List<MenuEntity> menuList = this.list();
                    // 存进redis缓存
                    redisTemplate.opsForValue().set(AuthConstant.MENU_CACHE, JSON.toJSONString(menuList),15, TimeUnit.MINUTES);
                    List<MenuVo> vos = this.tree(menuList);
                    return RespBean.success("获取菜单成功", vos);
                }
            }
            // 其他权限尚未设置待完善
        } else {
            return RespBean.error("用户不存在");
        }

        return null;
    }

    /**
     * 获取一级菜单
     * @return
     */
    @Override
    public RespBean getMenuLevel1() {
        String menu = redisTemplate.opsForValue().get(AuthConstant.MENU_CACHE);
        if(!StringUtils.isEmpty(menu)){
            // 如果redis缓存不为null
            List<MenuEntity> menuList = JSON.parseObject(menu, new TypeReference<List<MenuEntity>>() {
            });
            List<MenuEntity> collect = menuList.stream().filter(i -> i.getLevel() == 0).collect(Collectors.toList());
            collect.sort(new Comparator<MenuEntity>() {
                @Override
                public int compare(MenuEntity o1, MenuEntity o2) {
                    return o1.getSortOrder().compareTo(o2.getSortOrder());
                }
            });
            return RespBean.success("获取成功",collect);
        }else {
            // 如果缓存是null
            List<MenuEntity> menuList = this.list();
            redisTemplate.opsForValue().set(AuthConstant.MENU_CACHE, JSON.toJSONString(menuList),15, TimeUnit.MINUTES);
            List<MenuEntity> collect = menuList.stream().filter(i -> i.getLevel() == 0).collect(Collectors.toList());
            collect.sort(new Comparator<MenuEntity>() {
                @Override
                public int compare(MenuEntity o1, MenuEntity o2) {
                    return o1.getSortOrder().compareTo(o2.getSortOrder());
                }
            });
            return RespBean.success("获取成功",collect);
        }
    }

    /**
     * 获取菜单分类树
     * @return
     */
    @Override
    public List<MenuVo> getMenuTree(Long id) {
        MenuEntity menu = this.getById(id);
        if (menu!=null){
            String redis = redisTemplate.opsForValue().get(AuthConstant.MENU_CACHE);
            if(!StringUtils.isEmpty(redis)){
                List<MenuEntity> menuList = JSON.parseObject(redis, new TypeReference<List<MenuEntity>>() {
                });
                // 开始组装二级+3级菜单
                List<MenuVo> collect = menuList.stream().filter(i -> i.getLevel() == 1).map(level2 -> {
                    MenuVo menuVo2 = new MenuVo();
                    if (level2.getParentId().equals(menu.getId())) {
                        // 如果id对的上 进行属性对拷
                        BeanUtils.copyProperties(level2, menuVo2);

                        // 装三级菜单
                        List<MenuVo> collect2 = menuList.stream().filter(i -> i.getLevel() == 2).map(level3 -> {
                            MenuVo menuVo3 = new MenuVo();
                            if (level3.getParentId().equals(level2.getId())) {
                                BeanUtils.copyProperties(level3, menuVo3);
                                // 菜单最多三级
                            }
                            return menuVo3;
                        }).filter(i -> i.getId() != null).collect(Collectors.toList());

                        menuVo2.setChildren(collect2);

                    }
                    return menuVo2;
                }).filter(i -> i.getId() != null).collect(Collectors.toList());
                return collect;

            }else {
                List<MenuEntity> menuList = this.list();
                redisTemplate.opsForValue().set(AuthConstant.MENU_CACHE, JSON.toJSONString(menuList),15, TimeUnit.MINUTES);
                // 开始组装二级+3级菜单
                List<MenuVo> collect = menuList.stream().filter(i -> i.getLevel() == 1).map(level2 -> {
                    MenuVo menuVo2 = new MenuVo();
                    if (level2.getParentId().equals(menu.getId())) {
                        // 如果id对的上 进行属性对拷
                        BeanUtils.copyProperties(level2, menuVo2);

                        // 装三级菜单
                        List<MenuVo> collect2 = menuList.stream().filter(i -> i.getLevel() == 2).map(level3 -> {
                            MenuVo menuVo3 = new MenuVo();
                            if (level3.getParentId().equals(level2.getId())) {
                                BeanUtils.copyProperties(level3, menuVo3);
                                // 菜单最多三级
                            }
                            return menuVo3;
                        }).filter(i -> i.getId() != null).collect(Collectors.toList());

                        menuVo2.setChildren(collect2);

                    }
                    return menuVo2;
                }).filter(i -> i.getId() != null).collect(Collectors.toList());
                return collect;
            }
        }else {
            // 如果没查到直接返回null
            return null;
        }
    }

    /**
     * 添加菜单
     * @param menu
     * @return
     */
    @Override
    public RespBean addMenu(MenuEntity menu) {
        boolean b = this.saveOrUpdate(menu);
        if (b){
            return RespBean.success("添加菜单成功");
        }else {
            return RespBean.error("添加菜单失败");
        }

    }

    /**
     * 菜单树形结构封装
     * @param menuList
     * @return
     */
    private List<MenuVo> tree(List<MenuEntity> menuList) {
        // 收集1级菜单
        List<MenuVo> level1 = menuList.stream().filter(item -> {
            return item.getLevel() == 0;
        }).map(item -> {
            MenuVo menuVo = new MenuVo();
            BeanUtils.copyProperties(item, menuVo);
            return menuVo;
        }).collect(Collectors.toList());
        level1.sort(new Comparator<MenuVo>() {
            @Override
            public int compare(MenuVo o1, MenuVo o2) {
                return o1.getSortOrder().compareTo(o2.getSortOrder());
            }
        });


        for (MenuVo item1 : level1) {
            // 查询当前一级菜单对应的子菜单
            List<MenuVo> collect2 = menuList.stream().filter(i -> i.getLevel() == 1).map(level2 -> {
                MenuVo menuVo2 = new MenuVo(); // 要返回的二级菜单
                // 先过滤出来全部的二级分类
                if (level2.getParentId().equals(item1.getId())) {
                    // 如果父id匹配中
                    BeanUtils.copyProperties(level2,menuVo2);

                    // 找出三级菜单
                    List<MenuVo> collect3= menuList.stream().filter(i -> i.getLevel() == 2).map(level3 -> {
                        MenuVo menuVo3 = new MenuVo();
                        if (level3.getParentId().equals(level2.getId())) {
                            BeanUtils.copyProperties(level3, menuVo3);
                            // 菜单最多三级
                        }
                        return menuVo3;
                    }).filter(i -> i.getId() != null).collect(Collectors.toList());

                    // 设置三级菜单
                    menuVo2.setChildren(collect3);
                }
                return menuVo2;
            }).filter(i -> i.getId() != null).collect(Collectors.toList());


            // 设置子菜单
            item1.setChildren(collect2);
        }

        return level1;
    }


}
